package com.cyy.demo.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cyy.demo.utils.MapBeanUtil;
import com.cyy.demo.utils.ReflectionUtil;
import com.cyy.demo.utils.RestHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.ParameterizedType;
import java.util.Map;

/**
 * 基础service
 *
 * @author lilun
 */
public abstract class BaseService<T> {
    private static final Logger logger = LoggerFactory.getLogger(BaseService.class);


    /**
     * post请求
     *
     * @param restHelper
     * @param request
     * @param serviceName
     * @param url
     * @param param
     * @param clz
     * @return
     */
    public Object postRequestApi(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param, Class clz) {
        Object outObj = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            outObj = restHelper.combinedAssembly(parameter).postForObject(param, clz);
            logger.info("第三方接口返回信息:{}", JSON.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }

    /**
     * application/x-www-form-urlencoded格式的请求
     *
     * @param restHelper
     * @param request
     * @param serviceName
     * @param url
     * @param param
     * @param clz
     * @return
     */
    public Object postForFormUrlEncode(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param, Class clz) {
        Object outObj = null;
        try {
            Map<String,Object> realParams = MapBeanUtil.beanToMap(param,false);
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            outObj = restHelper.combinedAssembly(parameter).postForFormUrlEncode(realParams, clz);
            logger.info("第三方接口返回信息:{}", JSON.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }

    /**
     * form-data
     *
     * @param restHelper
     * @param request
     * @param serviceName
     * @param url
     * @param param
     * @param clz
     * @return
     */
    public Object postForFormData(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param, Class clz) {
        Object outObj = null;
        try {
            Map<String,Object> realParams = MapBeanUtil.beanToMap(param,false);
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            outObj = restHelper.combinedAssembly(parameter).postForFormData(realParams, clz);
            logger.info("第三方接口返回信息:{}", JSON.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }


    public T postRequestApi(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param) {
        Class<T> clz = getRealClass();
        T t = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            t = restHelper.combinedAssembly(parameter).postForObject(param, clz);
            logger.info("第三方接口返回信息:{}", JSONObject.toJSONString(t));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return (T) ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return t;
    }


    /**
     * get请求
     *
     * @param restHelper
     * @param request
     * @param serviceName
     * @param url
     * @param param
     * @return
     */
    public Object getRequestApi(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param, Class clz) {
        Object outObj = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            if (param == null) {
                outObj = restHelper.combinedAssembly(parameter).getForObject(clz);
            } else {
                outObj = restHelper.combinedAssembly(parameter).getForObject(param, clz);
            }
            logger.info("第三方接口返回信息:{}", JSONObject.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }

    public Object getForUrlParams(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Map<String, Object> param, Class clz) {
        Object outObj = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            outObj = restHelper.combinedAssembly(parameter).getForUrlParams(param, clz);
            logger.info("第三方接口返回信息:{}", JSONObject.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }


    public T getRequestApi(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param) {
        Class<T> clz = getRealClass();
        T t = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            if (param == null) {
                t = restHelper.combinedAssembly(parameter).getForObject(clz);
            } else {
                t = restHelper.combinedAssembly(parameter).getForObject(param, clz);
            }
            logger.info("第三方接口返回信息:{}", JSONObject.toJSONString(t));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return (T) ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return t;
    }

    public Object putRequestApi(RestHelper restHelper, HttpServletRequest request, String serviceName, String url, Object param, Class clz) {
        Object outObj = null;
        try {
            RestHelper.Parameter parameter = new RestHelper().new Parameter();
            parameter.addHttpServletRequest(request).addServiceName(serviceName).addUrl(url);
            outObj = restHelper.combinedAssembly(parameter).putForObject(param, clz);
            logger.info("第三方接口返回信息:{}", JSON.toJSONString(outObj));
        } catch (Exception e) {
            logger.error("invoke " + url + " error" + e.getMessage(), e);
            return ReflectionUtil.exeMethod(clz, "error", new Class[]{int.class, String.class}, new Object[]{500, "invoke " + url + " error"});
        }
        return outObj;
    }


    public Class<T> getRealClass() {
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        return (Class<T>) pt.getActualTypeArguments()[0];
    }

}
